package com.bii.gelapp;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Hashtable;

import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.Config;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

public class DNASegmentationActivity extends Activity {
	String analysisorigin = "";
	public Bitmap originalBmp; // origin
	public static Bitmap activeBmp; // edited image
	public static Bitmap takenBmp;
	public static Bitmap grayBmp;
	ImageView ivImage, ivLoading;
	EditText etMinsize;
	Button btEdge, btPrev, btCompare;
	public static int minsize = 450;
	ArrayList<ConnectedComponent> componentlist = new ArrayList<ConnectedComponent>();
	ArrayList<ConnectedComponent> markerlist = new ArrayList<ConnectedComponent>();
	//15 september
	ArrayList<ConnectedComponent> addedcomponentlist = new ArrayList<ConnectedComponent>();
	Mat destImg;

	int sigmatochange = 12;
	ProgressDialog dialog;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.dnasegmentationactivity);
		
		// instructions
				String donotshow = "";
				final Dialog instructiondialog = new Dialog(DNASegmentationActivity.this);
				instructiondialog.setContentView(R.layout.instructiondialog);
				instructiondialog.setTitle("Attention");
				instructiondialog.setCancelable(true);
				instructiondialog.setCancelable(false);

				TextView tvInstructions = (TextView) instructiondialog
						.findViewById(R.id.tvInstructions);
				ImageView imgView = (ImageView) instructiondialog
						.findViewById(R.id.ivInstructions);
				final CheckBox donotshowbox = (CheckBox) instructiondialog.findViewById(R.id.donotshow);
				Button btOk = (Button) instructiondialog.findViewById(R.id.btOk);

				final SharedPreferences donotshowinstructions = this.getSharedPreferences(
						"instructions", 0);
				donotshow = donotshowinstructions.getString("segmentationinstructions",
						"nothing");
				if (donotshow.equals("nothing")) {
					donotshow = "Show";
				}

				if (donotshow.equals("Show")) {
					tvInstructions.setText("Enter the minimum size of fragments, in pixels, for detection");
					
					Drawable drawable = getResources().getDrawable(R.drawable.segmentation_instructions);

					Bitmap instructionbmp = ((BitmapDrawable)drawable).getBitmap();
					
					imgView.setImageBitmap(instructionbmp);
					
					instructiondialog.show();

					btOk.setOnClickListener(new OnClickListener() {

						@Override
						public void onClick(View v) {
							// TODO Auto-generated method stub
							if(donotshowbox.isChecked()){
								SharedPreferences.Editor editor = donotshowinstructions.edit();
								editor.putString("segmentationinstructions", "DoNotShow");
								editor.commit();
							}
							else
							{
								SharedPreferences.Editor editor = donotshowinstructions.edit();
								editor.putString("segmentationinstructions", "Show");
								editor.commit();
							}
							instructiondialog.dismiss();
						}
					});
					
				}
				//
		
		if (getIntent().hasExtra("analysisorigin")) {
			analysisorigin = getIntent().getStringExtra("analysisorigin");
		}
		
		LinearLayout myLayout = (LinearLayout) findViewById(R.id.dnasegmentationlayout);
		myLayout.requestFocus();
		ivImage = (ImageView) findViewById(R.id.ivImage);
		ivImage.setEnabled(false);
		byte[] byteArray = getIntent().getByteArrayExtra("BMP");
		originalBmp = BitmapFactory.decodeByteArray(byteArray, 0,
				byteArray.length);
		/*
		// from fullscreen
		if (getIntent().hasExtra("activeBmp")) {
			byte[] byteArrayActive = getIntent().getByteArrayExtra("activeBmp");
			if (byteArrayActive.length != 0) {
				activeBmp = BitmapFactory.decodeByteArray(byteArrayActive, 0,
						byteArrayActive.length);
				Bitmap resizedbmp = Bitmap.createScaledBitmap(activeBmp, 300,
						300, true);
				ivImage.setImageBitmap(resizedbmp);
			} else {
				activeBmp = originalBmp;
				Bitmap resizedbmp = Bitmap.createScaledBitmap(originalBmp, 300,
						300, true);
				ivImage.setImageBitmap(resizedbmp);
			}
		} else {
			activeBmp = originalBmp;
			Bitmap resizedbmp = Bitmap.createScaledBitmap(originalBmp, 300,
					300, true);
			ivImage.setImageBitmap(resizedbmp);
		}
		*/

		//Bitmap resizedbmp = Bitmap.createScaledBitmap(originalBmp, 300, 300,
		//		true);
		//ivImage.setImageBitmap(resizedbmp);
		ivImage.setImageBitmap(originalBmp);

		etMinsize = (EditText) findViewById(R.id.etMinsize);
		//etMinsize.setText("" + 450);
		etMinsize.setHint("size to segment fragments");

		btEdge = (Button) findViewById(R.id.btEdge);

		btEdge.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				dialog = ProgressDialog.show(DNASegmentationActivity.this,
						"Loading", "Please wait");

				Thread th = new Thread(new Runnable() {

					@Override
					public void run() {
						// TODO Auto-generated method stub
						takenBmp = originalBmp;
						Mat srcImg = new Mat(takenBmp.getHeight(), takenBmp
								.getWidth(), CvType.CV_8U, new Scalar(4));
						int ch = srcImg.channels();
						Utils.bitmapToMat(takenBmp, srcImg);
						Imgproc.cvtColor(srcImg, srcImg, Imgproc.COLOR_BGR2GRAY);
						ch = srcImg.channels();
						ArrayList<ConnectedComponent> connectedComponentList = new ArrayList<ConnectedComponent>();
						destImg = new Mat();
						Imgproc.cvtColor(srcImg, destImg, Imgproc.COLOR_GRAY2BGR);
						minsize = Integer.parseInt(etMinsize.getText().toString());
						componentlist.clear();
						connectedComponentList.clear();
						markerlist.clear();
						findConnectedComponents(srcImg, destImg,
								connectedComponentList, minsize);
						Collections.sort(componentlist,
								new Comparator<ConnectedComponent>() {
									@Override
									public int compare(ConnectedComponent cc1,
											ConnectedComponent cc2) {
										return cc1.left - cc2.left;
									}
								});
						drawRectangles();

						Bitmap segmentedBmp = Bitmap.createBitmap(destImg.cols(),
								destImg.rows(), Bitmap.Config.RGB_565);
						Utils.matToBitmap(destImg, segmentedBmp);
						activeBmp = segmentedBmp;

						//Bitmap resizedbmp = Bitmap.createScaledBitmap(segmentedBmp,
						//		300, 300, true);
						//ivImage.setImageBitmap(resizedbmp);
						//ivImage.setEnabled(true);
						// btCompare.setEnabled(true);

						// gray test
						// convert bitmap to matrix
						grayBmp = RotationActivity.colorBmp
								.copy(Config.ARGB_8888, true);
						srcImg = new Mat(grayBmp.getHeight(), grayBmp.getWidth(),
								CvType.CV_8U, new Scalar(4));
						Bitmap myBitmap32 = grayBmp.copy(Bitmap.Config.ARGB_8888, true);
						Utils.bitmapToMat(myBitmap32, srcImg);
						Imgproc.cvtColor(srcImg, destImg, Imgproc.COLOR_BGR2GRAY);

						fixRectangles();
						//fixRectangles2();
						drawRectangles();

						grayBmp = Bitmap.createBitmap(destImg.cols(), destImg.rows(),
								Bitmap.Config.RGB_565);
						// convert mat back to bitmap set originalBmp;
						Utils.matToBitmap(destImg, grayBmp);
						// convert to grayscale
						//Mat grayImg = new Mat();
						activeBmp = grayBmp;

						//ivImage.setImageBitmap(grayBmp);
						//Toast.makeText(DNASegmentationActivity.this, "Click on image to edit fragments", Toast.LENGTH_SHORT).show();
						dialog.dismiss();
						runOnUiThread(new Runnable() // run on ui thread
						{

							@Override
							public void run() {

								ivImage.setImageBitmap(activeBmp);

							}

						});
					}
					
				});
				th.start();
				ivImage.setEnabled(true);
				//btCompare.setEnabled(true);

			}
		});

		ivImage.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent goToNextActivity = new Intent(getApplicationContext(),
						FullscreenActivity.class);
				goToNextActivity.putExtra("analysisorigin", analysisorigin);
				byte[] bytes;
				/*
				 * if (activeBmp == null) { bytes = compressImage(originalBmp);
				 * } else { bytes = compressImage(activeBmp); }
				 */
				bytes = compressImage(originalBmp);
				goToNextActivity.putExtra("BMP", bytes);
				byte[] bytes2;
				/*
				 * if (activeBmp == null) { bytes = compressImage(originalBmp);
				 * } else { bytes = compressImage(activeBmp); }
				 */
				bytes2 = compressImage(activeBmp);
				goToNextActivity.putExtra("BMP2", bytes2);

				goToNextActivity.putExtra("componentlist", componentlist);
				Collections.sort(markerlist,
						new Comparator<ConnectedComponent>() {
							@Override
							public int compare(ConnectedComponent cc1,
									ConnectedComponent cc2) {
								return cc1.top - cc2.top;
							}
						});
				goToNextActivity.putExtra("markerlist", markerlist);
				String origin = "Segmentation";
				goToNextActivity.putExtra("origin", origin);
				startActivity(goToNextActivity);

			}
		});

	}

	// srcImg MUST be a BINARY image
	public void findConnectedComponents(Mat srcImg, Mat destImg,
			ArrayList<ConnectedComponent> connectedComponentList, int minArea) {
		Hashtable<Integer, ConnectedComponent> conCompHt = new Hashtable<Integer, ConnectedComponent>();// from
																										// label
																										// to
																										// connected
																										// component
		int[][] labelMatrix = new int[srcImg.height()][srcImg.width()]; // all
																		// elements
																		// will
																		// be
																		// initialized
																		// with
																		// 0
		int issuedLabel = 0;

		System.out.println("Start finding connected components...");

		int temp = 0;
		for (int i = 1; i < srcImg.height() - 1; i++) {
			for (int j = 1; j < srcImg.width() - 1; j++) {
				double[] data = srcImg.get(i, j);
				if (data[0] <= 50) { // black pixel
					// if(data[0] > 50){
					if (labelMatrix[i][j - 1] != 0) {// the left neighbour pixel
														// has label (and of
														// course is black
														// pixel)
						labelMatrix[i][j] = labelMatrix[i][j - 1]; // label
																	// pixel
																	// (i,j),
																	// and admit
																	// it to the
																	// left
																	// neighbor
																	// pixel's
																	// connected
																	// component
						// UPDATE THE CONNECTED COMPONENT
						ConnectedComponent conComp = conCompHt
								.get(labelMatrix[i][j - 1]);
						if (conComp == null) {
							System.out.println(i + "\t" + j + "\t"
									+ labelMatrix[i][j]);
							System.out.println(labelMatrix[i][j - 1]);
							/*
							 * for (int g= 12;g<26;g++){ for (int f= 540; f<560;
							 * f++){ System.out.print(srcImg.get(g, f)[0]+"\t");
							 * } System.out.println(); }
							 * 
							 * for (int g= 12;g<26;g++){ for (int f= 540; f<560;
							 * f++){ System.out.print(labelMatrix[g][f]+"\t"); }
							 * System.out.println(); }
							 */
						}
						conComp.noPixels++;
						if (conComp.right < j)
							conComp.right = j;// no need to update the left, top
												// and bottom boundaries of the
												// connected component
						conCompHt.put(labelMatrix[i][j - 1], conComp);

						// MERGING THE CONNECTED COMPONENT WITH ITS NEIGHBOUR
						// CONNECTED COMPONENTS (If existing any)
						ConnectedComponent neighbourConComp;
						if (labelMatrix[i - 1][j - 1] != 0
								&& labelMatrix[i - 1][j - 1] != labelMatrix[i][j - 1]) {
							temp = labelMatrix[i - 1][j - 1];
							for (int e = j - 1; e < srcImg.width(); e++) {// update
																			// the
																			// labels
																			// of
																			// all
																			// pixels
																			// at
																			// the
																			// same
																			// line
																			// and
																			// have
																			// the
																			// same
																			// label
																			// as
																			// pixel
																			// (i-1,j-1)
								if (labelMatrix[i - 1][e] == temp)
									labelMatrix[i - 1][e] = labelMatrix[i][j - 1];
							}
							for (int e = j - 2; e > 0; e--) {// update the
																// labels of all
																// pixels at the
																// same line as
																// pixel (i,j)
																// and have the
																// same label as
																// pixel
																// (i-1,j-1)
								if (labelMatrix[i][e] == temp)
									labelMatrix[i][e] = labelMatrix[i][j - 1];
							}

							neighbourConComp = conCompHt.get(temp);
							conComp.noPixels += neighbourConComp.noPixels;
							if (neighbourConComp.left < conComp.left)
								conComp.left = neighbourConComp.left;
							if (neighbourConComp.right > conComp.right)
								conComp.right = neighbourConComp.right;
							if (neighbourConComp.top < conComp.top)
								conComp.top = neighbourConComp.top;// no need to
																	// update
																	// the
																	// bottom
																	// boundary
							conCompHt.put(labelMatrix[i][j - 1], conComp);
							conCompHt.remove(temp);// delete the neighbour
													// conComp after it is
													// merged
						}
						if (labelMatrix[i - 1][j] != 0
								&& labelMatrix[i - 1][j] != labelMatrix[i][j - 1]) {
							temp = labelMatrix[i - 1][j];
							for (int e = j; e < srcImg.width(); e++) {// update
																		// the
																		// labels
																		// of
																		// all
																		// pixels
																		// at
																		// the
																		// same
																		// line
																		// and
																		// have
																		// the
																		// same
																		// label
																		// as
																		// pixel
																		// (i-1,j)
								if (labelMatrix[i - 1][e] == temp)
									labelMatrix[i - 1][e] = labelMatrix[i][j - 1];
							}
							for (int e = j - 2; e > 0; e--) {// update the
																// labels of all
																// pixels at the
																// same line as
																// pixel (i,j)
																// and have the
																// same label as
																// pixel (i-1,j)
								if (labelMatrix[i][e] == temp)
									labelMatrix[i][e] = labelMatrix[i][j - 1];
							}

							neighbourConComp = conCompHt.get(temp);
							conComp.noPixels += neighbourConComp.noPixels;
							if (neighbourConComp.left < conComp.left)
								conComp.left = neighbourConComp.left;
							if (neighbourConComp.right > conComp.right)
								conComp.right = neighbourConComp.right;
							if (neighbourConComp.top < conComp.top)
								conComp.top = neighbourConComp.top;// no need to
																	// update
																	// the
																	// bottom
																	// boundary
							conCompHt.put(labelMatrix[i][j - 1], conComp);

							conCompHt.remove(temp);// delete the neighbour
													// conComp after it is
													// merged
						}
						// Log.d("tag1", i + " " + j);
						if (labelMatrix[i - 1][j + 1] != 0
								&& labelMatrix[i - 1][j + 1] != labelMatrix[i][j - 1]) {
							temp = labelMatrix[i - 1][j + 1];
							for (int e = j + 1; e < srcImg.width(); e++) {// update
																			// the
																			// labels
																			// of
																			// all
																			// pixels
																			// at
																			// the
																			// same
																			// line
																			// and
																			// have
																			// the
																			// same
																			// label
																			// as
																			// pixel
																			// (i-1,j+1)
								if (labelMatrix[i - 1][e] == temp)
									labelMatrix[i - 1][e] = labelMatrix[i][j - 1];
							}
							for (int e = j - 2; e > 0; e--) {// update the
																// labels of all
																// pixels at the
																// same line as
																// pixel (i,j)
																// and have the
																// same label as
																// pixel
																// (i-1,j+1)
								if (labelMatrix[i][e] == temp)
									labelMatrix[i][e] = labelMatrix[i][j - 1];
							}

							neighbourConComp = conCompHt.get(temp);
							conComp.noPixels += neighbourConComp.noPixels;
							if (neighbourConComp.left < conComp.left)
								conComp.left = neighbourConComp.left;
							if (neighbourConComp.right > conComp.right)
								conComp.right = neighbourConComp.right;
							if (neighbourConComp.top < conComp.top)
								conComp.top = neighbourConComp.top;// no need to
																	// update
																	// the
																	// bottom
																	// boundary
							conCompHt.put(labelMatrix[i][j - 1], conComp);
							conCompHt.remove(temp);// delete the neighbour
													// conComp after it is
													// merged
						}
					} else if (labelMatrix[i - 1][j - 1] != 0) {// the top-left
																// neighbour
																// pixel has
																// label (and of
																// course is
																// black pixel)
						labelMatrix[i][j] = labelMatrix[i - 1][j - 1]; // label
																		// pixel
																		// (i,j),
																		// and
																		// admit
																		// it to
																		// the
																		// top-left
																		// neighbor
																		// pixel's
																		// connected
																		// component
						// UPDATE THE CONNECTED COMPONENT
						ConnectedComponent conComp = conCompHt
								.get(labelMatrix[i - 1][j - 1]);
						conComp.noPixels++;
						if (conComp.right < j)
							conComp.right = j;
						if (conComp.bottom < i)
							conComp.bottom = i;// no need to update the left and
												// top boundaries of the
												// connected component
						conCompHt.put(labelMatrix[i - 1][j - 1], conComp);

						// MERGING THE CONNECTED COMPONENT WITH ITS NEIGHBOUR
						// CONNECTED COMPONENTS (If existing any)
						ConnectedComponent neighbourConComp;
						if (labelMatrix[i - 1][j] != 0
								&& labelMatrix[i - 1][j] != labelMatrix[i - 1][j - 1]) {
							// This will never happen because
							// labelMatrix[i-1][j] must become equal to
							// labelMatrix[i-1][j-1]
							// when line (i-1) was scanned previously
						}
						if (labelMatrix[i - 1][j + 1] != 0
								&& labelMatrix[i - 1][j + 1] != labelMatrix[i - 1][j - 1]) {
							temp = labelMatrix[i - 1][j + 1];
							for (int e = j + 1; e < srcImg.width(); e++) {// update
																			// the
																			// labels
																			// of
																			// all
																			// pixels
																			// at
																			// the
																			// same
																			// line
																			// and
																			// have
																			// the
																			// same
																			// label
																			// as
																			// pixel
																			// (i-1,j+1)
								if (labelMatrix[i - 1][e] == temp)
									labelMatrix[i - 1][e] = labelMatrix[i - 1][j - 1];
							}
							for (int e = j - 2; e > 0; e--) {// update the
																// labels of all
																// pixels at the
																// same line as
																// pixel (i,j)
																// and have the
																// same label as
																// pixel
																// (i-1,j+1)
								if (labelMatrix[i][e] == temp)
									labelMatrix[i][e] = labelMatrix[i - 1][j - 1];
							}

							neighbourConComp = conCompHt.get(temp);
							conComp.noPixels += neighbourConComp.noPixels;
							if (neighbourConComp.left < conComp.left)
								conComp.left = neighbourConComp.left;
							if (neighbourConComp.right > conComp.right)
								conComp.right = neighbourConComp.right;
							if (neighbourConComp.top < conComp.top)
								conComp.top = neighbourConComp.top;// no need to
																	// update
																	// the
																	// bottom
																	// boundary
							conCompHt.put(labelMatrix[i][j - 1], conComp);
							conCompHt.remove(temp);// delete the neighbour
													// conComp after it is
													// merged
						}

					} else if (labelMatrix[i - 1][j] != 0) {// the top neighbour
															// pixel has label
															// (and of course is
															// black pixel)
						labelMatrix[i][j] = labelMatrix[i - 1][j]; // label
																	// pixel
																	// (i,j),
																	// and admit
																	// it to the
																	// top
																	// neighbour
																	// pixel's
																	// connected
																	// component
						// UPDATE THE CONNECTED COMPONENT
						ConnectedComponent conComp = conCompHt
								.get(labelMatrix[i - 1][j]);
						conComp.noPixels++;
						if (conComp.bottom < i)
							conComp.bottom = i;// no need to update the left,
												// right and top boundaries of
												// the connected component
						conCompHt.put(labelMatrix[i - 1][j], conComp);

						// MERGING THE CONNECTED COMPONENT WITH ITS NEIGHBOUR
						// CONNECTED COMPONENTS (If existing any)
						// ConnectedComponent neighbourConComp;
						if (labelMatrix[i - 1][j + 1] != 0
								&& labelMatrix[i - 1][j + 1] != labelMatrix[i - 1][j]) {
							// This will never happen because
							// labelMatrix[i-1][j+1] must become equal to
							// labelMatrix[i-1][j]
							// when line (i-1) was scanned previously
						}
					} else if (labelMatrix[i - 1][j + 1] != 0) {// the top-right
																// neighbour
																// pixel has
																// label (and of
																// course is
																// black pixel)
						labelMatrix[i][j] = labelMatrix[i - 1][j + 1]; // label
																		// pixel
																		// (i,j),
																		// and
																		// admit
																		// it to
																		// the
																		// top-right
																		// neighbour
																		// pixel's
																		// connected
																		// component
						// UPDATE THE CONNECTED COMPONENT
						ConnectedComponent conComp = conCompHt
								.get(labelMatrix[i - 1][j + 1]);
						conComp.noPixels++;
						if (conComp.bottom < i)
							conComp.bottom = i;// no need to update the left,
												// right and top boundaries of
												// the connected component
						if (conComp.left > j)
							conComp.left = j;
						conCompHt.put(labelMatrix[i - 1][j + 1], conComp);
					} else {// there is none black pixels among the 4 neighbour
							// pixels of pixel (i,j)
							// CREATE A NEW CONNECTED COMPONENT FOR pixel (i,j)
						issuedLabel++;
						labelMatrix[i][j] = issuedLabel;
						ConnectedComponent conComp = new ConnectedComponent();
						conComp.noPixels = 1;
						conComp.label = issuedLabel;
						conComp.left = conComp.right = j;
						conComp.top = conComp.bottom = i;
						conCompHt.put(labelMatrix[i][j], conComp);
					}
				}// end if (data[0]<=50){ //pixel (i,j) is black
			}// end for j
		}// end for i
		System.out.println("Finnished finding connected components.");

		// LISTING ALL THE CONNECTED COMPONENTS
		Enumeration<Integer> en = conCompHt.keys();
		int label = 0;
		while (en.hasMoreElements()) {
			label = en.nextElement();
			connectedComponentList.add(conCompHt.get(label));
		}
		// update the connectedcomponent to offset the gabor filtering
		for (int i = 0; i < connectedComponentList.size(); i++) {

			ConnectedComponent cc = connectedComponentList.get(i);
		}

		// DRAW ALL THE CONNECTED COMPONENTS TO destImg (using rectangle bounds)
		for (int i = 0; i < connectedComponentList.size(); i++) {
			if (connectedComponentList.get(i).noPixels >= minArea) {
				if (connectedComponentList.get(i).bottom < originalBmp
						.getHeight()) {
					componentlist.add(connectedComponentList.get(i));
				} else {
					connectedComponentList.get(i).bottom = originalBmp
							.getHeight();
					componentlist.add(connectedComponentList.get(i));
				}
			}

		}

		System.out.println("Finnished drawing connected components.");
	}

	public void drawRectangles() {
		for (int i = 0; i < componentlist.size(); i++) {

			int top = componentlist.get(i).top;

			int bottom = componentlist.get(i).bottom;
			int left = componentlist.get(i).left;
			int right = componentlist.get(i).right;
			Core.rectangle(destImg, new Point(left, top), new Point(right,
					bottom), new Scalar(255, 0, 0), 2);

			int centerheight = (bottom + top) / 2;
			int centerwidth = (right + left) / 2;
			Point org = new Point(centerwidth, centerheight);
			Core.putText(destImg, "" + i, org, 3, 1, new Scalar(0, 0, 255), 5);

		}

	}

	public void fixRectangles() {
		Mat srcImg = new Mat(grayBmp.getHeight(), grayBmp.getWidth(),
				CvType.CV_8U, new Scalar(4));
		Bitmap myBitmap32 = grayBmp.copy(Bitmap.Config.ARGB_8888, true);
		Utils.bitmapToMat(myBitmap32, srcImg);

		// get initial intensity average
		for (int i = 0; i < componentlist.size(); i++) {
			int averageFragmentIntensity = 0;
			int j = 0;
			int k = 0;

			for (j = 0; j + componentlist.get(i).left <= componentlist.get(i).right; j++) {
				for (k = 0; k + componentlist.get(i).top <= componentlist
						.get(i).bottom; k++) {
					double[] intensity = srcImg.get(componentlist.get(i).top
							+ k, componentlist.get(i).left + j);
					averageFragmentIntensity += intensity[0];
				}
			}
			// test upwards first
			averageFragmentIntensity = averageFragmentIntensity
					/ ((componentlist.get(i).right - componentlist.get(i).left) * (componentlist
							.get(i).bottom - componentlist.get(i).top));
			upwardsTest(averageFragmentIntensity, componentlist.get(i), srcImg);
			Log.d("tag1",
					"component: " + i + " top: " + componentlist.get(i).top
							+ " bottom: " + componentlist.get(i).bottom);
			downwardsTest(averageFragmentIntensity, componentlist.get(i),
					srcImg);
		}
	}

	private void upwardsTest(int initialavg, ConnectedComponent cc, Mat srcImg) {
		boolean status = false;
		int initialtestavg = initialavg;
		// initial moving up of one pixel
		cc.top -= 1;
		cc.bottom -= 1;
		while (status != true) {
			int testavg = 0;
			int j = 0;
			int k = 0;
			for (j = 0; j + cc.left <= cc.right; j++) {

				for (k = 0; k + cc.top <= cc.bottom; k++) {
					if(k+cc.top >= 0){
						double[] intensity = srcImg.get(cc.top + k, cc.left + j);
						testavg += intensity[0];
					}
					else
					{
						status = true;
						break;
							
					}
				}

			}
			testavg = testavg / ((cc.right - cc.left) * (cc.bottom - cc.top));
			if (testavg >= initialtestavg) {
				initialtestavg = testavg;
				status = false;
				cc.top -= 1;
				cc.bottom -= 1;
			} else {
				status = true;
			}
		}
	}

	private void downwardsTest(int initialavg, ConnectedComponent cc, Mat srcImg) {
		boolean status = false;
		int initialtestavg = initialavg;
		// initial moving up of one pixel
		cc.top += 1;
		cc.bottom += 1;
		while (status != true) {
			int testavg = 0;
			int j = 0;
			int k = 0;

			for (j = 0; j + cc.left <= cc.right; j++) {
				for (k = 0; k + cc.top <= cc.bottom; k++) {
					// int intensity =
					// grayBmp.getPixel(componentlist.get(i).left + j,
					// componentlist.get(i).top + k);
					if(k+cc.top < srcImg.height()){
						double[] intensity = srcImg.get(cc.top + k, cc.left + j);
						testavg += intensity[0];
					}
					else
					{
						status = true;
						break;
					}

				}

			}
			testavg = testavg / ((cc.right - cc.left) * (cc.bottom - cc.top));
			if (cc.bottom + 1 >= grayBmp.getHeight()) {
				status = true;
			} else {
				if (testavg >= initialtestavg) {
					initialtestavg = testavg;
					status = false;
					cc.top += 1;
					cc.bottom += 1;
				} else {
					status = true;
				}
			}
		}
	}
	
	
	public void fixRectangles2() {
		Mat srcImg = new Mat(grayBmp.getHeight(), grayBmp.getWidth(),
				CvType.CV_8U, new Scalar(4));
		Bitmap myBitmap32 = grayBmp.copy(Bitmap.Config.ARGB_8888, true);
		Utils.bitmapToMat(myBitmap32, srcImg);

		ArrayList intensityList = new ArrayList();
		int averageFragmentIntensity = 0;
		for (int i = 0; i < componentlist.size(); i++) {
			for (int j = 0; j + componentlist.get(i).top <= componentlist
					.get(i).bottom; j++) {
				int rowintensity = 0;
				for (int k = 0; k + componentlist.get(i).left <= componentlist
						.get(i).right; k++) {
					double[] intensity = srcImg.get(componentlist.get(i).top,
							componentlist.get(i).left + k);
					rowintensity += intensity[0];
				}
				intensityList.add(rowintensity);
				averageFragmentIntensity += rowintensity;
			}
			
			averageFragmentIntensity = averageFragmentIntensity
					/ ((componentlist.get(i).right - componentlist.get(i).left) * (componentlist
							.get(i).bottom - componentlist.get(i).top));
			
			//test upwards
			upwardsTest2(intensityList, averageFragmentIntensity, componentlist.get(i), srcImg);
			downwardsTest2(intensityList, averageFragmentIntensity, componentlist.get(i), srcImg);
			
		}
		
		ArrayList markerintensityList = new ArrayList();
		int averagemarkerIntensity = 0;
		for (int i = 0; i < markerlist.size(); i++) {
			for (int j = 0; j + markerlist.get(i).top <= markerlist
					.get(i).bottom; j++) {
				int rowintensity = 0;
				for (int k = 0; k + markerlist.get(i).left <= markerlist
						.get(i).right; k++) {
					double[] intensity = srcImg.get(markerlist.get(i).top,
							markerlist.get(i).left + k);
					rowintensity += intensity[0];
				}
				markerintensityList.add(rowintensity);
				averagemarkerIntensity += rowintensity;
			}
			
			averagemarkerIntensity = averagemarkerIntensity
					/ ((markerlist.get(i).right - markerlist.get(i).left) * (markerlist
							.get(i).bottom - markerlist.get(i).top));
			
			//test upwards
			upwardsTest2(markerintensityList, averagemarkerIntensity, markerlist.get(i), srcImg);
			downwardsTest2(markerintensityList, averagemarkerIntensity, markerlist.get(i), srcImg);
			
		}
		
	}

	private void upwardsTest2(ArrayList initialintensitylist, int averageFragmentIntensity, ConnectedComponent cc, Mat srcImg) {
		boolean status = false;
		ArrayList testintensitylist = initialintensitylist;
		//test fragmentIntensity with testfragmentIntensity
		int testfragmentIntensity = averageFragmentIntensity;
		while(status != true)
		{
			int fragmentIntensity = 0;
			cc.top -= 1;
			cc.bottom -= 1;
			
			int rowintensity = 0;
			for (int k = 0; k + cc.left <= cc.right; k++) {
				double[] intensity = srcImg.get(cc.top, cc.left + k);
				rowintensity += intensity[0];
			}
			//upwards add top
			testintensitylist.add(0, rowintensity);
			//upwards remove bottom
			testintensitylist.remove(testintensitylist.size() - 1);
			
			for(int i = 0; i < testintensitylist.size(); i++){
				fragmentIntensity += (Integer)testintensitylist.get(i);
			}
			//average
			fragmentIntensity = fragmentIntensity
					/ ((cc.right - cc.left) * (cc.bottom - cc.top));
			//if brighter, continue to loop
			if (fragmentIntensity >= testfragmentIntensity) {
				//replace testfragmentIntensity with fragmentIntensity
				testfragmentIntensity = fragmentIntensity;
				status = false;
			} else {
				status = true;
			}
			
		}
	}

	private void downwardsTest2(ArrayList initialintensitylist, int averageFragmentIntensity, ConnectedComponent cc, Mat srcImg) {
		boolean status = false;
		ArrayList testintensitylist = initialintensitylist;
		//test fragmentIntensity with testfragmentIntensity
		int testfragmentIntensity = averageFragmentIntensity;
		while(status != true)
		{
			int fragmentIntensity = 0;
			cc.top += 1;
			cc.bottom += 1;
			
			int rowintensity = 0;
			for (int k = 0; k + cc.left <= cc.right; k++) {
				//reverse the calculation
				double[] intensity = srcImg.get(cc.bottom, cc.left + k);
				rowintensity += intensity[0];
			}
			//downwards add bottom
			testintensitylist.add(rowintensity);
			//downwards remove top
			testintensitylist.remove(0);
			
			for(int i = 0; i < testintensitylist.size(); i++){
				fragmentIntensity += (Integer)testintensitylist.get(i);
			}
			//average
			fragmentIntensity = fragmentIntensity
					/ ((cc.right - cc.left) * (cc.bottom - cc.top));
			//if brighter, continue to loop
			if (fragmentIntensity >= testfragmentIntensity) {
				//replace testfragmentIntensity with fragmentIntensity
				testfragmentIntensity = fragmentIntensity;
				status = false;
			} else {
				status = true;
			}
		}
			
	}

	public byte[] compressImage(Bitmap image) {
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		image.compress(Bitmap.CompressFormat.PNG, 0, stream);
		byte[] bytes = stream.toByteArray();
		return bytes;
	}
	
	private void fixLongfragments(int medianwidth, ConnectedComponent cc){
		int ccwidth = cc.right - cc.left;
		if(ccwidth > medianwidth)
		{
			int expectedwidthcount = Math.round(ccwidth / medianwidth); //cannot include cc itself
			int expectedwidth = Math.round(ccwidth / expectedwidthcount);
			
			cc.right = cc.left + expectedwidth;
			ConnectedComponent ccnew = new ConnectedComponent();
			for(int i = 0; i < expectedwidthcount-1; i++)
			{
				if(i == 0){
					ccnew.top = cc.top;
					ccnew.bottom = cc.bottom;
					ccnew.left = cc.right;
					ccnew.right = ccnew.left + expectedwidth;
					//add to addedcomponentlist, then add addedcomponentlist objects into componentlist
					addedcomponentlist.add(ccnew);
				}
				else
				{
					ccnew.top = ccnew.top;
					ccnew.bottom = ccnew.bottom;
					ccnew.left = ccnew.right;
					ccnew.right = ccnew.left + expectedwidth;
					addedcomponentlist.add(ccnew);
				}
			}
		}
	}

}
